﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using EnOceanReceiver;
using EnOceanTransmitter;
using EnOcean.Radio.Sensor;

namespace RelayController
{
  public partial class RelayControllerService : ServiceBase
  {
    private Receiver receiver;
    private Transmitter transmitter;
    private bool requiredTransmitterAvailable;

    public RelayControllerService()
    {
      InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
      List<long> sensors;

      sensors = new List<long>();
      sensors.Add(0x1C0B48);
      sensors.Add(0x15C331);

      requiredTransmitterAvailable = false;

      try
      {
        receiver = new Receiver(sensors);
        receiver.TelegramReceived += new EventHandler<TelegramReceivedEventArgs>(TelegramReceived);
        receiver.Start();

        transmitter = new Transmitter();
        transmitter.TransmitterAvailable += new EventHandler(TransmitterAvailabillityChanged);
        transmitter.TransmitterUnavailable += new EventHandler(TransmitterAvailabillityChanged);
        transmitter.UnhandledException += new EventHandler<UnhandledExceptionEventArgs>(TransmitterUnhandledException);
        transmitter.Start();
      }
      catch (Exception e)
      {
        EventLog.WriteEntry(e.ToString(), EventLogEntryType.Error);
      }
    }

    protected override void OnStop()
    {
      try
      {
        receiver.Stop();
        transmitter.Stop();
      }
      catch (Exception e)
      {
        EventLog.WriteEntry(e.ToString(), EventLogEntryType.Error);
      }
    }

    private void TransmitterUnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
      EventLog.WriteEntry(e.ExceptionObject.ToString(), EventLogEntryType.Error);
    }

    private void TransmitterAvailabillityChanged(object sender, EventArgs e)
    {
      try
      {
        if (transmitter.GetAvailableBaseIds().Contains(0xFFCC6D00))
        {
          requiredTransmitterAvailable = true;
          EventLog.WriteEntry("TransmitterAvailable", EventLogEntryType.Information);
        }
        else
        {
          requiredTransmitterAvailable = false;
          EventLog.WriteEntry("TransmitterUnavailable", EventLogEntryType.Information);
        }
      }
      catch (Exception ex)
      {
        EventLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
      }
    }

    private void TelegramReceived(object sender, TelegramReceivedEventArgs e)
    {
      RepeatedSwitchNTelegram s;

      try
      {
        if (requiredTransmitterAvailable)
        {
          if (e.Telegram is RepeatedSwitchNTelegram)
          {
            s = (RepeatedSwitchNTelegram)e.Telegram;
            
            if (s.HasSecondAction == false) // Two button press is used for controlling another relay.
            {
              if (s.Id == 0x1C0B48 || s.Id == 0x15C331)
              {
                s.Id = 0xFFCC6D01;
                s.TelegramType = EnOcean.TelegramType.TransmitRadioTelegram;
                transmitter.Send(s);
              }
            }
          }
        }
      }
      catch (Exception ex)
      {
        EventLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
      }
    }


    private string DisplayRepeatedSwitchNTelegram(RepeatedSwitchNTelegram t)
    {
      StringBuilder sb;

      sb = new StringBuilder();

      sb.AppendLine("Id               : " + t.Id.ToString("X8"));
      sb.AppendLine("SwitchType       : " + t.SwitchType);
      sb.AppendLine("RepeatCounter    : " + t.RepeatCounter);
      sb.AppendLine("EnergyBowPressed : " + t.IsEnergyBowPressed);
      sb.AppendLine("FirstButtonId    : " + t.FirstButtonId);
      sb.AppendLine("FirstButtonState : " + t.FirstButtonState);

      if (t.HasSecondAction)
      {
        sb.AppendLine("SecondAction     : " + t.HasSecondAction);
        sb.AppendLine("SecondButtonId   : " + t.SecondButtonId);
        sb.AppendLine("SecondButtonState: " + t.SecondButtonState);
      }

      return sb.ToString();
    }
  }
}
